#pragma once
#include <QObject>
#include <iostream>
#include <map>
#include <mutex>
#include <future>//提供了一种访问异步操作结果的机制
#include <functional>
//#include "Model_Base.h"
//#include "Model/Data_Definition/Fileinfo.h"
//#include "setuptask_thread.h"
#include "Data/FileContextWrapper.h"
#include "Data/FileInfo.h"
#include  "Data/AVPacket/AVPacketManager.h"
#include "DesignPattern/ISubject.h"
#include "DesignPattern/Observer.h"

#include "DesignPattern/DataObserver.h"
#include "fileMangent.h"
#include "DesignPattern/NoDataObserver.h"



class FileMangent :  public QObject,public NoDataObserver
{
   Q_OBJECT
public:
    ~FileMangent(){std::cout <<__TIME__<<":"<< __FUNCTION__<< std::endl;}
/*********************  instance *****************************/
	FileMangent(const FileMangent&)=delete;
	FileMangent& operator=(const FileMangent&)=delete;

	static FileMangent& get_instance()
	{
		static FileMangent instance;
		return instance;
    }
    static std::shared_ptr<FileMangent> get_instance_ptr() {
        FileMangent& instance = get_instance();
        static std::shared_ptr<char> anchor(new char, [&instance](char* p) {
            delete p;
            // Do nothing with instance. This is a no-op deleter.
        });
        return {anchor, &instance};
    }
    void init() {
        audio_queue.init();
        video_queue.init();
    }
/***************************************************/
    void accept(ObserverVisitor& visitor, ISubject* subject) override {
    //    visitor.visitDataObserver(this, subject, data_);
    }
    void onPlaybackStarted() override;

    void onPlaybackStopped() override;

/************************************************/     
     class setuptask_thread
    {
        public:
            setuptask_thread(){};
            void set_taskbobject(AVFormatContextWrapper &);
            std::atomic_bool start_thread_{false};
            void run(FileMangent* file_mangent);
        private:
            bool setfileinfo(AVFormatContextWrapper &);
            AVFormatContextWrapper m_fileobject;
    };
/**************************************************************************/  
    AVPacketManager& get_audio_queue() { return audio_queue; }
    AVPacketManager& get_video_queue() { return video_queue; }

     const AVFormatContextWrapper::AVCodecContextPtr & get_audio_codec_context() {
        return audio_codec_context_;
     }
     const AVFormatContextWrapper::AVCodecContextPtr & get_video_codec_context() {
        return video_codec_context_;
     }
/**************************************************************************/     
     void updateFileInfo(FileInfo& info,
                         AVFormatContextWrapper::AVCodecContextPtr audio_codec_ctx,
                         AVFormatContextWrapper::AVCodecContextPtr video_codec_ctx);
    FileInfo getFileInfo(const std::string& filename) {
        std::unique_lock<std::mutex> lock(files_map_mutex);
        auto iter = m_files_map.find(filename);
        if (iter != m_files_map.end()) {
            return iter->second;
        }
        return FileInfo();
    }
    bool can_open_stream();
    bool resetAndReadFrames();
    //set Operation
    bool addfile(const std::string &);
    bool setcurrentfile(const std::string &);
//clean Operation
    bool removefile(AVFormatContextWrapper &);
    void CleanAll();
//get Operation
    const std::string & getcurrentfile();
    size_t getfilecount();
    std::shared_ptr <std::thread> m_pthread;

     
signals:
    void fileInformationReceived(const FileInfo& info);
private:
    FileMangent();
    AVFormatContextWrapper::AVCodecContextPtr audio_codec_context_;
    AVFormatContextWrapper::AVCodecContextPtr video_codec_context_;

    AVFormatContextWrapper av_format_ctx_wrapper;
    AVFormatContextWrapper new_format_ctx_wrapper;
    bool removefile(const std::string &);
    std::string  m_current_filename;

    std::mutex files_map_mutex; 

    setuptask_thread set_works;

    std::map<std::string, std::unique_ptr<AVFormatContextWrapper>> m_files_format;
    std::map<std::string, FileInfo> m_files_map;   

    std::atomic<bool> m_playback_running{false};

    AVPacketManager audio_queue;
    AVPacketManager video_queue;

    //work finish flag
    std::atomic<bool> m_work_finish{false};     

    void playback_thread_func();
};

